/**
* \file usart.c
* \brief 串口驱动
*	2.2020-01-16,
*
* \author mirlee
* \version 0.2
* \date 2019-08-02
*/
#include "boot_drv.h"


/**
 * @brief mbl_recv_byte
 * @note 读取一个字节
 * @param 
 * @retval 0,读取成功;-1,读取失败
 */
#if (STM32F103x || STM32F429x)
int mbl_recv_byte(unsigned char *c, int timeout)
{
	int t;
	t=timeout*500;
	//RXNE
	while(t--)
	{
		if(USARTxx->SR & 0x20)
		{
			*c = (unsigned char)USARTxx->DR;
			return 0;
		}
	}
	return -1;
}

int mbl_send_byte(char c)
{
	while(!(USARTxx->SR & 0x80));
	USARTxx->DR = (uint16_t)c;
	return 0;
}

#elif STM32F030x
int mbl_recv_byte(unsigned char *c, int timeout)
{
	int t;
	t=timeout*500;
	//RXNE
	while(t--)
	{
		if(USARTxx->ISR & 0x20)
		{
			*c = (unsigned char)USARTxx->RDR;
			return 0;
		}
		if(USARTxx->ISR & 0x08)
		{
			USARTxx->ICR |=  0x01UL<<3;
			return -2;
		}
	}
	return -1;
}

int mbl_send_byte(char c)
{
	while(!(USARTxx->ISR & 0x80));
	USARTxx->TDR = (uint16_t)c;
	return 0;
}

#endif
void mbl_delay_ms(int ms)
{
	int i=8000;
	i*=ms;
	while(i--);
}
/**
  * @brief System Clock Configuration
  * @retval None
  */
void mbl_sys_clk_init(void)
{

#if(STM32F030x)
  LL_FLASH_SetLatency(LL_FLASH_LATENCY_0);

  if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0)
  {
		while(1);
  }
  //LL_RCC_HSE_Enable();
	LL_RCC_HSI_Enable();
	while(LL_RCC_HSI_IsReady() != 1)
  {    
  }
  LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI_DIV_2, LL_RCC_PLL_MUL_2);
  LL_RCC_PLL_Enable();

   /* Wait till PLL is ready */
  while(LL_RCC_PLL_IsReady() != 1)
  {    
  }
  LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
  LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
  LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);

   /* Wait till System clock is ready */
  while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
  {  
  }
	/*SystemCoreClock=8000000*/
#elif (STM32F103x)
  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  /* Set HSION bit */
  RCCxx->CR |= 0x00000001U;
  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#if !defined(STM32F105xC) && !defined(STM32F107xC)
  RCCxx->CFGR &= 0xF8FF0000U;
#else
  RCCx->CFGR &= 0xF0FF0000U;
#endif /* STM32F105xC */   
  /* Reset HSEON, CSSON and PLLON bits */
  RCCxx->CR &= 0xFEF6FFFFU;
  /* Reset HSEBYP bit */
  RCCxx->CR &= 0xFFFBFFFFU;
  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  RCCxx->CFGR &= 0xFF80FFFFU;
#if defined(STM32F105xC) || defined(STM32F107xC)
  /* Reset PLL2ON and PLL3ON bits */
  RCCx->CR &= 0xEBFFFFFFU;
  /* Disable all interrupts and clear pending bits  */
  RCCx->CIR = 0x00FF0000U;
  /* Reset CFGR2 register */
  RCCx->CFGR2 = 0x00000000U;
#elif defined(STM32F100xB) || defined(STM32F100xE)
  /* Disable all interrupts and clear pending bits  */
  RCCx->CIR = 0x009F0000U;
  /* Reset CFGR2 register */
  RCCx->CFGR2 = 0x00000000U;      
#else
  /* Disable all interrupts and clear pending bits  */
  RCCxx->CIR = 0x009F0000U;
#endif /* STM32F105xC */
  SCB->VTOR = 0x08000000UL; /* Vector Table Relocation in Internal FLASH. */
	
	
	/*Set FLASH Latency*/
	MODIFY_REG(FLASH->ACR,FLASH_ACR_LATENCY,0x00000000U);
	/*Set HSI Calibration trimming*/
	MODIFY_REG(RCCxx->CR, RCC_CR_HSITRIM, 16 << 3U);
	/*Enable HSI oscillator*/
	SET_BIT(RCCxx->CR, RCC_CR_HSION);
	/* Wait till HSI is ready */
	while(!(READ_BIT(RCCxx->CR, RCC_CR_HSIRDY) == (RCC_CR_HSIRDY)));
	/*Set AHB prescaler*/
	MODIFY_REG(RCCxx->CFGR, RCC_CFGR_HPRE, 0x00000000U);
	/*Set APB1 prescaler*/
	MODIFY_REG(RCCxx->CFGR, RCC_CFGR_PPRE1, 0x00000000U);
	/*Set APB2 prescaler*/
	MODIFY_REG(RCCxx->CFGR, RCC_CFGR_PPRE2, 0x00000000U);
	/*Configure the system clock source*/
  /*HSI selected as system clock */
	MODIFY_REG(RCCxx->CFGR, RCC_CFGR_SW, 0x00000000U);
	/* Wait till System clock is ready */
	while(READ_BIT(RCCxx->CFGR, RCC_CFGR_SWS) != 0x00000000U);
	/*SystemCoreClock=8000000*/
#elif (STM32F429x)

	SCB->VTOR = 0x08000000UL; /* Vector Table Relocation in Internal FLASH. */
	/*Set FLASH Latency 0*/
	MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, 0x00000000U);
	//Set the main internal Regulator output voltage
	MODIFY_REG(PWR->CR, PWR_CR_VOS, PWR_CR_VOS_0);
	//Disable Over drive Mode
	CLEAR_BIT(PWR->CR, PWR_CR_ODEN);
	//Set HSI Calibration trimming
	MODIFY_REG(RCCxx->CR, RCC_CR_HSITRIM, 16 << 3U);
	/*Enable HSI oscillator*/
	SET_BIT(RCCxx->CR, RCC_CR_HSION);
	/* Wait till HSI is ready */
	while(!(READ_BIT(RCCxx->CR, RCC_CR_HSIRDY) == (RCC_CR_HSIRDY)));
	/*Set AHB prescaler*/
	//two divided-frequency
	MODIFY_REG(RCCxx->CFGR, RCC_CFGR_HPRE, 0x00000080U);
	/*Set APB1 prescaler*/
	//HCLK not divided
	MODIFY_REG(RCCxx->CFGR, RCC_CFGR_PPRE1, 0x00000000U);
	/*Set APB2 prescaler*/
	//HCLK not divided
	MODIFY_REG(RCCxx->CFGR, RCC_CFGR_PPRE2, 0x00000000U);
	/*Configure the system clock source*/
  /*HSI selected as system clock */
	MODIFY_REG(RCCxx->CFGR, RCC_CFGR_SW, 0x00000000U);
	
	/* Wait till System clock is ready */
	while(READ_BIT(RCCxx->CFGR, RCC_CFGR_SWS) != 0x00000000U);
	/*SystemCoreClock=8000000*/
#endif
}

void mbl_usart_init(void )
{
	/**USART1 GPIO Configuration  
  PA9   ------> USART1_TX
  PA10   ------> USART1_RX 
  */
	
	/**USART1 GPIO Configuration  
  PA9   ------> USART1_TX
  PA10   ------> USART1_RX 
  */
	//** FHP2A04 
	/**USART2 GPIO Configuration  
  PA2   ------> USART2_TX
  PA3   ------> USART2_RX 
  */
	
	float temp;
	int mantissa;//整数
	int fraction;//小数
	
	//USART1使用pclk2 USART2-5使用PCLK1
	temp=(float)(8000000)/(float)(115200*16);
	mantissa=temp;        //整数部分
	fraction=(temp-mantissa)*16;
	mantissa<<=4;
	mantissa=mantissa+fraction;
#if (STM32F030x)
	/*1. clk enable*/
	RCCxx->AHBENR |= 1<<17;//IOPAEN
	RCCxx->APB1ENR |= 1<<17;//USART2EN
	/*2. io init*/
	GPIOxx->MODER &=0XFFFFFF0F;
	GPIOxx->MODER |=0X000000A0;
	GPIOxx->AFR[0] &= ~0x1100;
	GPIOxx->AFR[0] |= 0x1100;
	/*3. reset usart1 */
	RCCxx->APB1RSTR|=1<<17; //复位串口 2
	RCCxx->APB1RSTR&=~(1<<17);//停止复位
	/*4. init usart1*/
	USARTxx->BRR =  mantissa;  //波特率
	USARTxx->CR1 |= 0XD;    //usart1使能,发送接收使能
#elif (STM32F103x)
	/*1. clk enable*/
	RCCxx->APB2ENR |= 1<<2;//IOPAEN
	RCCxx->APB2ENR |= 1<<14;//USART1EN
	/*2. io init*/
	GPIOxx->CRH &=0XFFFFF00F;
	GPIOxx->CRH |=0X000004B0;
	/*3. reset usart1 */
	RCCxx->APB2RSTR|=1<<14; //复位串口 1
	RCCxx->APB2RSTR&=~(1<<14);//停止复位
	/*4. init usart1*/
	USARTxx->BRR =  mantissa;  //波特率
	USARTxx->CR1 |= 0X200C;    //usart1使能,发送接收使能
#elif (STM32F429x)
	/*1. clk enable*/
	RCCxx->AHB1ENR |= 0x1UL;//IOPAEN
	RCCxx->APB2ENR  |=0x1UL<<4U;//USART1EN
	/*2. io init*/
	for(int i=9;i<=10;i++)
	{
		MODIFY_REG(GPIOxx->OSPEEDR, (0x3UL << (i * 2U)), \
							 (0x3UL << (i * 2U)));//speed high
		MODIFY_REG(GPIOxx->OTYPER, (0x1UL << i), (0x00000000U << i));//push-pull
		MODIFY_REG(GPIOxx->PUPDR, (0x3UL << (i * 2U)), (0x1UL << (i * 2U)));//pull up
		//注意下面设置参数区分引脚位置
		//设置复用的接口
		MODIFY_REG(GPIOxx->AFR[1], (0xFUL << ((i-8) * 4U)), \
							 (0x0000007U << ((i-8) * 4U)));
		//设置引脚模式
		MODIFY_REG(GPIOxx->MODER, (0x3UL << (i * 2U)), (0x2UL << (i * 2U)));
	}
	/*3. reset usart1 */
	RCCxx->APB2RSTR|=1<<4; //复位串口 1
	RCCxx->APB2RSTR&=~(1<<4);//停止复位	
	
	/* In Asynchronous mode, the following bits must be kept cleared:
  - LINEN, CLKEN bits in the USART_CR2 register,
  - SCEN, IREN and HDSEL bits in the USART_CR3 register.*/
	#define USART_CR2_LINEN               (0x1UL << 14U)  /*!<LIN mode enable */
	#define USART_CR2_CLKEN               (0x1UL << 11U)  /*!<Clock Enable  */
	#define USART_CR3_SCEN                (0x1UL << 5U)   /*!<Smartcard mode enable*/
	#define USART_CR3_IREN                (0x1UL << 1U)   /*!<IrDA mode Enable  */
	#define USART_CR3_HDSEL               (0x1UL << 3U)   /*!<Half-Duplex Selection       */
  CLEAR_BIT(USARTxx->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
  CLEAR_BIT(USARTxx->CR3, (USART_CR3_SCEN | USART_CR3_IREN | USART_CR3_HDSEL));
	/*4. init usart1*/
	USARTxx->BRR =  mantissa;  //波特率
	USARTxx->CR1 |= 0X200C;    //usart1使能,发送接收使能
#endif
}


/**
 * @brief 系统初始化
 * @retval None
 */
void SystemInit(void)
{
	/*Alternate Function I/O clock enable*/
	/*用于复用jtag io*/
	//SET_BIT(RCCxx->APB2ENR, 0x1UL);
	/*Power interface clock enable */
	//SET_BIT(RCCxx->APB1ENR, 0x1UL<<28U);
	/*JTAG-DP Disabled and SW-DP Enabled*/
	//CLEAR_BIT(AFIOxx->MAPR,AFIO_MAPR_SWJ_CFG);
  //SET_BIT(AFIOxx->MAPR, AFIO_MAPR_SWJ_CFG_JTAGDISABLE);
	
	//LL_APB2_GRP1_EnableClock(RCC_APB2ENR_SYSCFGEN);
  //LL_APB1_GRP1_EnableClock(RCC_APB1ENR_PWREN);

	mbl_sys_clk_init();
	mbl_usart_init();
}









